#include "socket_cache_thread.h"

#include "business_def.h"
#include "dtypedef.h"
#include "datadef.h"
#include "pfunc.h"
#include "Log.h"
#ifdef __linux__
#include <stdexcept>
#endif
#ifdef WIN32
#define usleep(x) Sleep(x)
#endif


SocketCacheThread::SocketCacheThread(void)
	: running(true)
	, ptr_bdef(BusinessDef::getInstance())
	, socket_cache_queue(QueueDataSingle<DataFromChannel>::getInstance())
{
	socket_cache_queue->setQueueDesc("data_from_gchannel");
}

SocketCacheThread::~SocketCacheThread(void)
{
	running = false;
}

void* SocketCacheThread::run()
{
	DataFromChannel data_from_gather;
	while (running)
	{
		if (socket_cache_queue->getFirst(data_from_gather))
		{
			this->AddFrame(data_from_gather.flag, data_from_gather.Buf, data_from_gather.len);
			socket_cache_queue->removeFirst();
		}
		usleep(1);
	}
	return 0;
}

int SocketCacheThread::AddFrame(const std::string link, const unsigned char *buf, int len)
{
	//const unsigned char * buff = buf;
	try {
		unsigned char * pBuf = new unsigned char[len];
		int nLen = pyfree::uncode(buf, len, pBuf);
		unsigned char type = pBuf[0];
		int idx = 1;
		switch (type)
		{
		case 0XF7:
		{
			int blen = pBuf[idx++];
			blen += (pBuf[idx++] << 8);
			if ((blen+1)!=nLen) 
			{
				break;
			}
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);
			pyfree::PType pType = (pyfree::PType)pBuf[idx++];
			float Value = float(0.0);
			unsigned char* fval = (unsigned char*)&Value;
			fval[3] = pBuf[idx++];
			fval[2] = pBuf[idx++];
			fval[1] = pBuf[idx++];
			fval[0] = pBuf[idx++];
			fval = NULL;
			//task id
			unsigned long taskID = 0;
			taskID += pBuf[idx++];
			taskID += (pBuf[idx++] << 8);
			taskID += (pBuf[idx++] << 16);
			taskID += (pBuf[idx++] << 24);
			//end
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrame\r\n");
			}
			if (pyfree::OnYX == pType) 
			{
				Value = Value > 0 ? float(1.0) : float(0.0);
			}
			ptr_bdef->setValue(link, pID, pType, Value, taskID);
			// Print_NOTICE("read data 0XF7:link[%s],pID[%d],pType[%d],val[%.3f]],endflag[%02X]\n"
			// 	,link.c_str(),pID,pType,Value, endflag);
		}
		break;
		case 0XF8:
		{
			int blen = pBuf[idx++];
			blen += (pBuf[idx++] << 8);
			if ((blen + 1) != nLen) 
			{
				break;
			}
			int psize = pBuf[idx++];
			psize += (pBuf[idx++] << 8);
			if ((13*psize + 6) != nLen) 
			{
				break;
			}
			for (int i = 0; i < psize; ++i) 
			{
				int pID = 0;
				pID += pBuf[idx++];
				pID += (pBuf[idx++] << 8);
				pID += (pBuf[idx++] << 16);
				pID += (pBuf[idx++] << 24);
				pyfree::PType pType = (pyfree::PType)pBuf[idx++];
				float Value = float(0.0);
				unsigned char* fval = (unsigned char*)&Value;
				fval[3] = pBuf[idx++];
				fval[2] = pBuf[idx++];
				fval[1] = pBuf[idx++];
				fval[0] = pBuf[idx++];
				fval = NULL;
				//task id
				unsigned long taskID = 0;
				taskID += pBuf[idx++];
				taskID += (pBuf[idx++] << 8);
				taskID += (pBuf[idx++] << 16);
				taskID += (pBuf[idx++] << 24);
				//
				if (pyfree::OnYX == pType) 
				{
					Value = Value > 0 ? float(1.0) : float(0.0);
				}
				ptr_bdef->setValue(link, pID, pType, Value, taskID);
				// Print_NOTICE("read data 0XF8:link[%s],pID[%d],pType[%d],val[%.3f]],taskID[%lu]\n"
				// 	, link.c_str(), pID, pType, Value, taskID);
			}
			//end
			unsigned char endflag = pBuf[idx++];
			if (0XFF!= endflag)
			{
				Print_WARN("error end for frame data in AddFrame\r\n");
			}
		}
		break;
		case 0XF9:
		{
			Print_NOTICE("heartbeat from client!\n");
		}
		break;
		default:
		{
			delete[] pBuf;
			pBuf = NULL;
			//
			char warBuf[128] = { 0 };
			sprintf(warBuf, "ExxCacheThread::AddFrame For Unkown Type(%02X)", type);
			#ifdef WIN32
			throw std::exception(warBuf);
			#else
			throw std::domain_error(warBuf);
			#endif
			//throw type;
		}
		//break;
		}
		delete[] pBuf;
		pBuf = NULL;
		return 1;
	}
	catch (const std::exception& e)
	{
		CLogger::createInstance()->Log(MsgError,
			"AddFrame(%s,%s,%d) have error[%s],[%s %s %d]"
			, link.c_str(), buf, len
			, e.what()
			, __FILE__, __FUNCTION__, __LINE__);
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgError,
			"AddFrame error[%s,%s,%d],[%s %s %d]!"
			, link.c_str(), buf, len
			, __FILE__, __FUNCTION__, __LINE__);
	}
	return -1;
};